package com.plsjavaweb.dao.utilities;


import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;

import javax.naming.NamingException;

import org.apache.log4j.Logger;

import com.plsjavaweb.dao.DAOFactory;
import com.plsjavaweb.dao.mapper.Mapper;
import com.plsjavaweb.logging.LoggingConstants;

public class DAO<T> {
	static Logger log= Logger.getLogger(DAOFactory.class);
	static LoggingConstants logConst = new LoggingConstants();
	
	public List<T> ExecuteQuery(String queryString, Mapper<T> mapper) {
		log.info(logConst.entryMessage);
	
		Statement stmt = null;
		Connection con = null;
		ResultSet rs = null;

		try
		{
	log.info(logConst.tryMessage);
			con = ConnectionFactory.getConnection();

			//calling using inline query
			stmt = con.createStatement();
			String query = queryString;
			rs = stmt.executeQuery(query);

			//for future enhancement use stored procedure
			//use  list/map of parameters which sets the type
			//calling using an prepared statement or stored procedure
			//		        proc=con.prepareCall("{call GetUserAccountByUsername(?)}");
			//		        rs=proc.executeQuery();
			//		        
			//create the prepare call statement using the parameter array of strings
			//create the 
			//		        StringBuilder callStm;
			//		        callStm.append("{call " + storedProcedureName + " ");
			//		        for(int i=0; i<parameter.length;i++){
			//		        	if(i==0){
			//		        		callStm.append("?");
			//		        	}else{
			//		        		callStm.append(",?");
			//		        	}
			//		        	proc.setString(i+1, parameter(i));
			//			        
			//		        };
			//		        callStm.append(")}");



			// Maps the list to Java object
			
			log.info(logConst.returnedMessage);
			return mapper.MapList(rs);

		}
		catch (SQLException e) {
			log.error(e.getMessage());
			e.printStackTrace();
		} catch (NamingException e) {
			log.error(e.getMessage());
			e.printStackTrace();
		} finally{
			log.error("entred finally");
			if(stmt != null){
				try {
					stmt.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

				if(con != null){
					try {
						con.close();
					} catch (SQLException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}
		log.error(logConst.returnedMessage);
		return null;

	}

	// Returns a Generic Type using a Mapper Interface as parameter
	public T ExecuteQuerySingle(String query, Mapper<T> mapper) {
		log.info(logConst.entryMessage);
		Statement stmt = null;
		Connection con = null;
		ResultSet rs = null;

		try
		{
			log.info(logConst.tryMessage);
			con = ConnectionFactory.getConnection();

			//calling using inline query
			stmt = con.createStatement();
			rs = stmt.executeQuery(query);
			return mapper.MapObject(rs);

		} 		catch (SQLException e) {
			log.error(e.getMessage());
			e.printStackTrace();
		} catch (NamingException e) {
			log.error(e.getMessage());
			e.printStackTrace();
		} finally{
			log.info("enter finally.");
			if(stmt != null){
				try {
					stmt.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

				if(con != null){
					try {
						con.close();
					} catch (SQLException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}
log.info(logConst.returnedMessage);
		return null;
	}

}
